package com.sdp.irrigation.server.netty.channel;

import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.sdp.irrigation.server.netty.model.ChannelSession;

import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelId;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.util.AttributeKey;
import io.netty.util.concurrent.GlobalEventExecutor;

public class ChannelManager implements IChannelManager {

	private final AttributeKey<ChannelSession> CHANNEL_SESSION = AttributeKey.newInstance("session");
	
	private ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
	
	private final Map<String, Map<String, ChannelId>> channelIdMap;
	
	private Logger logger = LoggerFactory.getLogger(ChannelManager.class);
	
	private ChannelFutureListener remover = new ChannelFutureListener() {
		
		@Override
		public void operationComplete(ChannelFuture future) throws Exception {
			ChannelSession session = future.channel().attr(CHANNEL_SESSION).get();
			if (session != null) {
				String telNo = session.getTelNo();
				if (!StringUtils.isEmpty(telNo)) {
					if (channelIdMap.containsKey(telNo)) {
						channelIdMap.get(telNo).remove(future.channel().id().toString());
					}
//					channelIdMap.remove(telNo);
//					SubPackageDataManager.removeSubPackageData(telNo);
				}
				logger.info("设备断开连接, 设备编号为：[{}]  客户端ip为：[{}], channelId: [{}]", StringUtils.isEmpty(telNo) ? "无" : telNo, future.channel().remoteAddress(), future.channel().id());
			}
			
		}
	};
	
	public ChannelManager(int initialCapacity) {
		channelIdMap = new ConcurrentHashMap<>(initialCapacity);
	}
	
	public boolean initChannel(Channel channel) {
		boolean added = channelGroup.add(channel);
		if (added) {
			ChannelSession session = new ChannelSession();
			session.setId(channel.id().toString());
			channel.attr(CHANNEL_SESSION).set(session);
			channel.closeFuture().addListener(remover);
		}
		return added;
	}
	
	public boolean addMap(String telNo, Channel channel) {
		boolean added = false;
		Channel channelFind = channelGroup.find(channel.id());
		if (channelFind != null) {
			ChannelSession session = channel.attr(CHANNEL_SESSION).get();
			session.setTelNo(telNo);
			if (!channelIdMap.containsKey(telNo)) {
				channelIdMap.put(telNo, new ConcurrentHashMap<>());
			}
			channelIdMap.get(telNo).put(channel.id().toString(), channel.id());
			//channelIdMap.put(telNo, channel.id());
		}
		return added;
	}

//	public boolean remove(String telNo) {
//        return channelGroup.remove(channelIdMap.remove(telNo));
//    }

    public Set<Channel> get(String telNo) {
    	Set<Channel> channelSet = new HashSet<>();
    	Map<String, ChannelId> map = channelIdMap.get(telNo);
    	if (map != null) {
        	for (ChannelId channelId : map.values()) {
        		Channel channel = channelGroup.find(channelId);
        		if (channel != null) {
        			channelSet.add(channel);
				}
    		}
        	
		}
    	return channelSet;
    }

    public ChannelGroup getChannelGroup() {
        return channelGroup;
    }
    
    public boolean isChannelExist(ChannelId channelId) {
    	return channelGroup.find(channelId) != null;
    }
	
    public ChannelSession getSession(ChannelId channelId) {
    	if (channelId != null) {
    		Channel channel = channelGroup.find(channelId);
    		if (channel != null) {
    			return channel.attr(CHANNEL_SESSION).get();
			}
		}
        return null;
    }
    
//    public ChannelSession getSession(String telNo)
//    {
//    	ChannelId channelId = channelIdMap.get(telNo);
//		if (channelId != null) {
//			Channel channel = channelGroup.find(channelId);
//    		if (channel != null) {
//    			return channel.attr(CHANNEL_SESSION).get();
//			}
//		}
//		return null;
//    }
    
//	public void setSession(String telNo, ChannelSession session)
//	{
//		ChannelId channelId = channelIdMap.get(telNo);
//		if (channelId != null) {
//			Channel channel = channelGroup.find(channelId);
//			if (channel != null) {
//				channel.attr(CHANNEL_SESSION).set(session);
//			}
//		}
//	}
    
    public int getChannelSize()
    {
    	return channelIdMap.size();
    }
    
    public void destroy() {
    	channelGroup.close();
    }

	@Override
	public Map<String, Map<String, ChannelId>> getChannelIdMap() {
		return channelIdMap;
	}

    
}
